home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume21 / rayshade / part03 < prev    next >
Encoding:
Internet Message Format  |  1990-03-21  |  56.1 KB

  1. Subject:  v21i010:  A ray tracing program, Part03/08
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Craig Kolb <craig@weedeater.math.yale.edu>
  7. Posting-number: Volume 21, Issue 10
  8. Archive-name: rayshade/part03
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 3 (of 8)."
  17. # Contents:  BLURB.UTAH src/bounds.c src/cone.c src/cylinder.c
  18. #   src/intersect.c src/light.c src/object.c src/ray_options.c
  19. #   src/voxels.c
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'BLURB.UTAH' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'BLURB.UTAH'\"
  23. else
  24. echo shar: Extracting \"'BLURB.UTAH'\" \(6402 characters\)
  25. sed "s/^X//" >'BLURB.UTAH' <<'END_OF_FILE'
  26. X
  27. X               THE UTAH RASTER TOOLKIT
  28. X
  29. XThe Utah Raster toolkit is a collection of programs and C routines for
  30. Xdealing with raster images commonly encountered in computer graphics.  It
  31. Xprovides the following major functions:
  32. X
  33. X    * A device and system independent image format for storing images
  34. X      and information about them.  Called the RLE format, it uses
  35. X      run length encoding to reduce storage space for most images.
  36. X
  37. X    * A library of C routines for reading, writing and manipulating
  38. X      images stored in the RLE format.
  39. X
  40. X    * A collections of programs for manipulating and displaying RLE
  41. X      images.
  42. X
  43. X
  44. XThe Format:
  45. X
  46. X  The device independent RLE file has two parts, the header, which stores
  47. X  information about the image (size, position, channel information,
  48. X  color maps, comments, etc), and the actual image data in a run length
  49. X  encoded format.  The RLE format often requires about a third of the
  50. X  available space for most "image synthesis" style images.  If the image
  51. X  does not compress well, the RLE format stores it as straight pixel data
  52. X  with little extra overhead.  The format has been developed over the past
  53. X  five years at Utah.
  54. X
  55. XThe Library:
  56. X
  57. X  C routines are provided for setting up and reading the image header,
  58. X  and for reading and writing the image a scanline at a time.  Images can
  59. X  be read or written using two different methods.  Using the "row" method,
  60. X  the library performs the RLE encoding and decoding.  With the "raw" method,
  61. X  scanlines are constructed directly with RLE opcodes.  Additional routines
  62. X  are available for generating dither matrices (e.g., for display programs
  63. X  running on devices with less than 24 bits of color).
  64. X
  65. XThe Tools:
  66. X  applymap   - Apply color map values to pixel values.
  67. X  avg4          - Downfilter an image by 1/4, generating a matte channel if one
  68. X           didn't previously exist
  69. X  comp          - Digital image compositor.  Provides the operations over, atop,
  70. X           in, out, xor, plus, minus and diff on two images.
  71. X  crop          - Crop an image.
  72. X  dvi2rle    - Convert TeX output into anti-aliased images.
  73. X  fant          - Rotate and/or scale in image by an arbitrary (float) value.
  74. X  mcut       - Quantize an image from 24 to eight bits using the median cut
  75. X           algorithm.
  76. X  mergechan  - Merge several channels from different files into a single
  77. X           RLE file.
  78. X  pyrmask    - Blend images using Gaussian pyrimids.
  79. X  repos      - Change the position in the RLE header.
  80. X  rleClock   - Generate an image of a clock.
  81. X  rleaddcom  - Add a comment to the RLE file's header.
  82. X  rlebg      - Generate a solid or variable background.
  83. X  rlebox     - Find the actual non-background area of an image.
  84. X  rleflip    - Rotate an image by 90/180 degree increments.
  85. X  rlehdr     - Dump the contents of the RLE header in human readable form.
  86. X  rlehisto   - Generate the histogram of an RLE file.
  87. X  rleldmap   - Load a color map into an RLE file from a variety of sources.
  88. X  rlemandl   - Generate Mandlebrot sets as RLE files.
  89. X  rlenoise   - Adds random noise to an image.    
  90. X  rlepatch   - Overlay several smaller images over a larger one.
  91. X  rlescale   - Generates gray scale and color scale RLE files.
  92. X  rlesetbg   - Set the background color stored in the RLE header.
  93. X  rlesplit   - Split a file containing several images into several files.
  94. X  rleswap    - Swap, copy or delete channels in an RLE file.
  95. X  rletops    - Convert an RLE image to PostScript (graylevel).
  96. X  rlezoom    - Enlarge an image with pixel replication.
  97. X  smush      - Perform a simple Gaussian filter on an image.
  98. X  to8          - Convert a 24 bit RGB image to an eight bit dithered one.
  99. X  tobw          - Convert 24 bits to 8 bits black and white.
  100. X  unexp      - Convert an "exponential" image to a displayable one.
  101. X  unslice    - Quickly assemble an image from several horizontal strips
  102. X
  103. X  Format conversion programs are provided for:
  104. X       - Simple pixel streams (color & B&W)
  105. X    - Targa image format
  106. X    - Cubicomp image format
  107. X    - PostScript
  108. X    - MacPaint
  109. X    - Sun rasterfiles
  110. X    - Wastatch paint systems
  111. X
  112. X  Display programs are provided for:
  113. X  getap         - Apollo workstations
  114. X  getbob     - HP Series 300 ("bobocat") running Windows 9000
  115. X  getcx3d    - Chromatics CX1500 display
  116. X  getfb      - BRL "libfb" displays
  117. X  getgmr     - Grinnell GMR-27 (remember those?)
  118. X  getX         - Workstations running the X window system
  119. X  getX11     - Workstations running X11
  120. X  getOrion   - Orion displays
  121. X  getren     - HP 98721 "Rennasance" display
  122. X  getsun     - Suns running Suntools
  123. X  getmac     - Macintosh.
  124. X  getmex     - Iris running Mex
  125. X  getqcr     - Photograph images with the Matrix QCR-Z camera.
  126. X  getiris    - Iris in raw 24 bit mode.
  127. X             - [Note display programs for a particular device are
  128. X        simple to add]
  129. X
  130. X  All the tools are designed to pipe together, so they can be used as 
  131. X  filters on images much like the standard Unix tools filter text.
  132. X
  133. XPlus:
  134. X
  135. X  The raster toolkit also includes Unix man pages for the library and
  136. X  commands, some sample images, and additional documentation.
  137. X
  138. XSystem Requirements:
  139. X
  140. X  We have successfully ported the Raster Toolkit to a number of Unix
  141. X  systems, including 4.2/4.3bsd (Vax, Sun, etc), Apollo Domain/IX, HP
  142. X  Series 3000, SGI Iris, Gould UTX.  Display programs are included for
  143. X  several devices.  Creating display programs for additional devices is
  144. X  a straightforward task.
  145. X
  146. XDistribution:
  147. X
  148. X  For ARPAnet sites, the toolkit may be obtained via anonymous FTP to the
  149. X  site cs.utah.edu, in the file pub/toolkit-2.0.tar (or, if you cannot FTP
  150. X  that large a file at once, in pub/toolkit-2.0.tar.1, pub/toolkit-2.0.tar.2
  151. X  and pub/toolkit-2.0.tar.3).  Sites not on the ARPAnet can obtain the Raster
  152. X  Toolkit on a 9-track, 1600 bpi tar format tape by sending check or
  153. X  money order for $200.00, payable to the Department of Computer Science,
  154. X  to:
  155. X
  156. X    Attn: Utah Raster Toolkit, Loretta Looser
  157. X    Department of Computer Science
  158. X    University of Utah
  159. X     Salt Lake City, UT, 84112
  160. X
  161. X  Courtesy Mike Muuss at BRL, the Raster Toolkit is also included as
  162. X  contributed software in the BRL-CAD distribution.
  163. X
  164. X  [Note: because of the size of the distribution, we can not distribute
  165. X  it via mail or UUCP]
  166. X
  167. X  Although the Raster Toolkit software is copyrighted, it may be freely 
  168. X  re-distributed on a "GNU-like" basis.
  169. X
  170. XFor further technical information on the Raster Toolkit, send mail
  171. Xto:
  172. X    toolkit-request@cs.utah.edu        (ARPA)
  173. X    {ihnp4,decvax}!utah-cs!toolkit-request    (UUCP)
  174. X
  175. X
  176. END_OF_FILE
  177. if test 6402 -ne `wc -c <'BLURB.UTAH'`; then
  178.     echo shar: \"'BLURB.UTAH'\" unpacked with wrong size!
  179. fi
  180. chmod +x 'BLURB.UTAH'
  181. # end of 'BLURB.UTAH'
  182. fi
  183. if test -f 'src/bounds.c' -a "${1}" != "-c" ; then 
  184.   echo shar: Will not clobber existing file \"'src/bounds.c'\"
  185. else
  186. echo shar: Extracting \"'src/bounds.c'\" \(5679 characters\)
  187. sed "s/^X//" >'src/bounds.c' <<'END_OF_FILE'
  188. X/*
  189. X * bounds.c
  190. X *
  191. X * Copyright (C) 1989, Craig E. Kolb
  192. X *
  193. X * This software may be freely copied, modified, and redistributed,
  194. X * provided that this copyright notice is preserved on all copies.
  195. X *
  196. X * There is no warranty or other guarantee of fitness for this software,
  197. X * it is provided solely .  Bug reports or fixes may be sent
  198. X * to the author, who may or may not act on them as he desires.
  199. X *
  200. X * You may not include this software in a program or other software product
  201. X * without supplying the source, or without informing the end-user that the
  202. X * source is available for no extra charge.
  203. X *
  204. X * If you modify this software, you should include a notice giving the
  205. X * name of the person performing the modification, the date of modification,
  206. X * and the reason for such modification.
  207. X *
  208. X * $Id: bounds.c,v 3.0 89/10/27 02:05:46 craig Exp $
  209. X *
  210. X * $Log:    bounds.c,v $
  211. X * Revision 3.0  89/10/27  02:05:46  craig
  212. X * Baseline for first official release.
  213. X * 
  214. X */
  215. X#include <stdio.h>
  216. X#include <math.h>
  217. X#include "constants.h"
  218. X#include "typedefs.h"
  219. X#include "funcdefs.h"
  220. X
  221. X#ifndef HUGE
  222. X#define HUGE    1.701411e38
  223. X#endif
  224. X
  225. X/*
  226. X * Ray-bounding box intersection test.
  227. X */
  228. Xdouble
  229. XIntBounds(ray, bounds)
  230. XRay *ray;
  231. Xdouble bounds[2][3];
  232. X{
  233. X    double t, tmin, tmax, bmin, bmax;
  234. X    double dir, pos;
  235. X    extern unsigned long BVTests;
  236. X
  237. X    BVTests++;
  238. X    tmin = 0.;
  239. X    tmax = FAR_AWAY;
  240. X
  241. X    dir = ray->dir.x;
  242. X    pos = ray->pos.x;
  243. X
  244. X    if (dir < 0) {
  245. X        bmin = bounds[HIGH][X];
  246. X        bmax = bounds[LOW][X];
  247. X    } else {
  248. X        bmax = bounds[HIGH][X];
  249. X        bmin = bounds[LOW][X];
  250. X    }
  251. X
  252. X    if (dir != 0.) {        /* check x-faces */
  253. X        t = (bmax - pos) / dir;
  254. X        if (t < 0.)
  255. X            return 0.;
  256. X        if (t <= tmax)
  257. X            tmax = t;
  258. X        t = (bmin - pos) / dir;
  259. X        if (t >= 0.) {
  260. X            if (t > tmax)
  261. X                return 0.;
  262. X            tmin = t;
  263. X        }
  264. X    } else if (pos < bmin || pos > bmax)
  265. X        return 0.;
  266. X
  267. X    dir = ray->dir.y;
  268. X    pos = ray->pos.y;
  269. X
  270. X    if (dir < 0) {
  271. X        bmin = bounds[HIGH][Y];
  272. X        bmax = bounds[LOW][Y];
  273. X    } else {
  274. X        bmax = bounds[HIGH][Y];
  275. X        bmin = bounds[LOW][Y];
  276. X    }
  277. X
  278. X    if (dir != 0.) {        /* check y-faces */
  279. X        t = (bmax - pos) / dir;
  280. X        if (t < 0.)
  281. X            return 0.;
  282. X        if (t <= tmax) {
  283. X            if (t < tmin)
  284. X                return 0.;
  285. X            tmax = t;
  286. X        }
  287. X        t = (bmin - pos) / dir;
  288. X        if (t >= tmin) {
  289. X            if (t > tmax)
  290. X                return 0.;
  291. X            tmin = t;
  292. X        }
  293. X    } else if (pos < bmin || pos > bmax)
  294. X        return 0.;
  295. X
  296. X    dir = ray->dir.z;
  297. X    pos = ray->pos.z;
  298. X
  299. X    if (dir < 0) {
  300. X        bmin = bounds[HIGH][Z];
  301. X        bmax = bounds[LOW][Z];
  302. X    } else {
  303. X        bmax = bounds[HIGH][Z];
  304. X        bmin = bounds[LOW][Z];
  305. X    }
  306. X
  307. X    if (dir != 0.) {        /* check z-faces */
  308. X        t = (bmax - pos) / dir;
  309. X        if (t < 0.)
  310. X            return 0.;
  311. X        if (t <= tmax) {
  312. X            if (t < tmin)
  313. X                return 0.;
  314. X            tmax = t;
  315. X        }
  316. X        t = (bmin - pos) / dir;
  317. X        if (t >= tmin) {
  318. X            if (t > tmax)
  319. X                return 0.;
  320. X            tmin = t;
  321. X        }
  322. X    } else if (pos < bmin || pos > bmax)
  323. X        return 0.;
  324. X
  325. X    return tmin;
  326. X}
  327. X
  328. X/*
  329. X * Transform an object's bounding box by the given transformation
  330. X * matrix.
  331. X */
  332. Xtransform_bounds(trans, objbounds)
  333. XTransInfo *trans;
  334. Xdouble objbounds[2][3];
  335. X{
  336. X    Vector v, tmp;
  337. X    double bounds[2][3];
  338. X    int x, y, z;
  339. X
  340. X    init_bounds(bounds);
  341. X
  342. X    /*
  343. X     * Find bounding box of transformed corners of bounding box.
  344. X     */
  345. X    for (x = 0 ; x < 2; x++) {
  346. X        v.x = objbounds[x][X];
  347. X        for (y = 0; y < 2; y++) {
  348. X            v.y = objbounds[y][Y];
  349. X            for (z = 0; z < 2; z++) {
  350. X                v.z = objbounds[z][Z];
  351. X                tmp = v;
  352. X                transform_point(&tmp, trans);
  353. X                if (tmp.x < bounds[LOW][X])
  354. X                    bounds[LOW][X] = tmp.x;
  355. X                if (tmp.x > bounds[HIGH][X])
  356. X                    bounds[HIGH][X] = tmp.x;
  357. X                if (tmp.y < bounds[LOW][Y])
  358. X                    bounds[LOW][Y] = tmp.y;
  359. X                if (tmp.y > bounds[HIGH][Y])
  360. X                    bounds[HIGH][Y] = tmp.y;
  361. X                if (tmp.z < bounds[LOW][Z])
  362. X                    bounds[LOW][Z] = tmp.z;
  363. X                if (tmp.z > bounds[HIGH][Z])
  364. X                    bounds[HIGH][Z] = tmp.z;
  365. X            }
  366. X        }
  367. X    }
  368. X
  369. X    for (x = 0; x < 3; x++) {
  370. X        objbounds[LOW][x] = bounds[LOW][x];
  371. X        objbounds[HIGH][x] = bounds[HIGH][x];
  372. X    }
  373. X}
  374. X
  375. Xinit_bounds(bounds)
  376. Xdouble bounds[2][3];
  377. X{
  378. X    bounds[LOW][X] = bounds[LOW][Y] = bounds[LOW][Z] = HUGE;
  379. X    bounds[HIGH][X] = bounds[HIGH][Y] = bounds[HIGH][Z] = -HUGE;
  380. X}
  381. X
  382. X/*
  383. X * Walk through a linked-list of objects.  If the object is unbounded,
  384. X * unlink it it from the list and add it to the 'unbounded' list.
  385. X * If the object is bounded, enlarge the given bounding box if
  386. X * necessary.  Return pointer to unbounded list.
  387. X */
  388. XObjList *
  389. Xfind_bounds(list, bounds)
  390. XObjList **list;
  391. Xdouble bounds[2][3];
  392. X{
  393. X    ObjList *ltmp, *prev, *oltmp;
  394. X    ObjList *unbounded;
  395. X    Object *otmp;
  396. X
  397. X    init_bounds(bounds);
  398. X    prev = unbounded = (ObjList *)0;
  399. X
  400. X    for (ltmp = *list; ltmp; ltmp = ltmp->next) {
  401. X        otmp = ltmp->data;
  402. X        if (otmp->bounds[LOW][X] > otmp->bounds[HIGH][X]) {
  403. X            /*
  404. X             * Object is unbounded -- unlink it...
  405. X             */
  406. X            if (prev)
  407. X                prev->next = ltmp->next;
  408. X            else
  409. X                *list = ltmp->next;
  410. X            /*
  411. X             * And add it to unbounded object list.
  412. X             */
  413. X            oltmp = (ObjList *)Malloc(sizeof(ObjList));
  414. X            oltmp->data = otmp;
  415. X            oltmp->next = unbounded;
  416. X            unbounded = oltmp;
  417. X        } else {
  418. X            /*
  419. X             * Object is bounded.
  420. X             */
  421. X            enlarge_bounds(bounds, otmp->bounds);
  422. X            prev = ltmp;
  423. X        }
  424. X    }
  425. X    return unbounded;
  426. X}
  427. X
  428. X#define SetIfLess(a, b)        (a = (a) < (b) ? (a) : (b))
  429. X#define SetIfGreater(a, b)    (a = (a) > (b) ? (a) : (b))
  430. X
  431. X/*
  432. X * Find bounding box of the union of two bounding boxes.
  433. X */
  434. Xenlarge_bounds(old, new)
  435. Xdouble old[2][3], new[2][3];
  436. X{
  437. X    SetIfLess(old[LOW][X], new[LOW][X]);
  438. X    SetIfLess(old[LOW][Y], new[LOW][Y]);
  439. X    SetIfLess(old[LOW][Z], new[LOW][Z]);
  440. X    SetIfGreater(old[HIGH][X], new[HIGH][X]);
  441. X    SetIfGreater(old[HIGH][Y], new[HIGH][Y]);
  442. X    SetIfGreater(old[HIGH][Z], new[HIGH][Z]);
  443. X}
  444. X
  445. Xprint_bounds(box)
  446. Xdouble box[2][3];
  447. X{
  448. X    extern FILE *fstats;
  449. X    fprintf(fstats,"\tX: %f to %f\n",box[LOW][X], box[HIGH][X]);
  450. X    fprintf(fstats,"\tY: %f to %f\n",box[LOW][Y], box[HIGH][Y]);
  451. X    fprintf(fstats,"\tZ: %f to %f\n",box[LOW][Z], box[HIGH][Z]);
  452. X}
  453. END_OF_FILE
  454. if test 5679 -ne `wc -c <'src/bounds.c'`; then
  455.     echo shar: \"'src/bounds.c'\" unpacked with wrong size!
  456. fi
  457. # end of 'src/bounds.c'
  458. fi
  459. if test -f 'src/cone.c' -a "${1}" != "-c" ; then 
  460.   echo shar: Will not clobber existing file \"'src/cone.c'\"
  461. else
  462. echo shar: Extracting \"'src/cone.c'\" \(6421 characters\)
  463. sed "s/^X//" >'src/cone.c' <<'END_OF_FILE'
  464. X/*
  465. X * cone.c
  466. X *
  467. X * Copyright (C) 1989, Craig E. Kolb
  468. X *
  469. X * This software may be freely copied, modified, and redistributed,
  470. X * provided that this copyright notice is preserved on all copies.
  471. X *
  472. X * There is no warranty or other guarantee of fitness for this software,
  473. X * it is provided solely .  Bug reports or fixes may be sent
  474. X * to the author, who may or may not act on them as he desires.
  475. X *
  476. X * You may not include this software in a program or other software product
  477. X * without supplying the source, or without informing the end-user that the
  478. X * source is available for no extra charge.
  479. X *
  480. X * If you modify this software, you should include a notice giving the
  481. X * name of the person performing the modification, the date of modification,
  482. X * and the reason for such modification.
  483. X *
  484. X * $Id: cone.c,v 3.0 89/10/27 02:05:47 craig Exp $
  485. X *
  486. X * $Log:    cone.c,v $
  487. X * Revision 3.0  89/10/27  02:05:47  craig
  488. X * Baseline for first official release.
  489. X * 
  490. X */
  491. X#include <stdio.h>
  492. X#include <math.h>
  493. X#include "typedefs.h"
  494. X#include "funcdefs.h"
  495. X#include "constants.h"
  496. X
  497. XObject *
  498. Xmakcone(surf, cent, ax, br, ar, trans)
  499. Xchar *surf;
  500. XVector *cent, *ax;
  501. Xdouble br, ar;
  502. XTransInfo *trans;
  503. X{
  504. X    Cone *cone;
  505. X    Primitive *prim;
  506. X    Object *newobj;
  507. X    extern int yylineno, Quiet;
  508. X    double len, dtmp;
  509. X    Vector axis, base, tmp;
  510. X
  511. X    prim = mallocprim();
  512. X    prim->surf = find_surface(surf);
  513. X    prim->type = CONE;
  514. X    newobj = new_object(NULL, CONE, (char *)prim, (Trans *)NULL);
  515. X    cone = (Cone *)Malloc(sizeof(Cone));
  516. X    prim->objpnt.p_cone = cone;
  517. X
  518. X    /*
  519. X     * Cones are defined by a basepoint, an apex point, and
  520. X     * base and apex radii.  The cone is stored as
  521. X     * the origin of the cone, the change in radius per
  522. X     * unit distance from the origin of the cone, the maximum z-value
  523. X     * of the cone, and "start_pos",
  524. X     * the distance along the axis from the cone origin where
  525. X     * the first endcap appears (where the passed "basepoint"
  526. X     * appears).
  527. X     *
  528. X     * The intcone() routine intersects a ray with a cone aligned
  529. X     * along the Z axis.  Thus, we must define a transformation
  530. X     * matrix which will transform an axis-aligned cone to the desired.
  531. X     */
  532. X
  533. X    /*
  534. X     * The passed basepoint must be closer to the origin of the
  535. X     * cone than the apex point, implying that the base radius
  536. X     * must be smaller than the apex radius.  If the values passed
  537. X     * reflect the opposite, we switch everything.
  538. X     */
  539. X    if(ar < br) {
  540. X        tmp = *cent;
  541. X        *cent = *ax;
  542. X        *ax = tmp;
  543. X        dtmp = br;
  544. X        br = ar;
  545. X        ar = dtmp;
  546. X    } else if (equal(ar, br)) {
  547. X        /*
  548. X         * If the base and apex radii are equal, then we
  549. X         * can treat the cone as a cylinder.
  550. X         */
  551. X        return makcyl(surf, cent, ax, br, trans);
  552. X    }
  553. X    /*
  554. X     * Find the axis and axis length.
  555. X     */
  556. X    vecsub(*ax, *cent, &axis);
  557. X    len = normalize(&axis);
  558. X    if (len < EPSILON) {
  559. X        if (!Quiet)
  560. X            fprintf(stderr,"Degenerate cone (line %d).\n",
  561. X                            yylineno);
  562. X        free((char *)cone);
  563. X        free((char *)prim);
  564. X        free((char *)newobj);
  565. X        return (Object *)0;
  566. X    }
  567. X    cone->apex_rad = ar;
  568. X    /*
  569. X     * "tantheta" is the change in radius per unit length along
  570. X     * the cone axis.
  571. X     */
  572. X    cone->tantheta = (ar - br) / len;
  573. X    /*
  574. X     * Start pos defines the point along the axis where the first
  575. X     * endcap should be placed.
  576. X     */
  577. X    cone->start_pos = br / cone->tantheta;
  578. X    /*
  579. X     * Find the true base (origin) of the cone.
  580. X     */
  581. X    scalar_prod(-cone->start_pos, axis, &base);
  582. X    vecadd(base, *cent, &base);
  583. X    /*
  584. X     * The apex endcap is placed cone->len units from the cone
  585. X     * origin.
  586. X     */
  587. X    cone->end_pos = cone->start_pos + len;
  588. X    /*
  589. X     * Calculate rotation matrix to map from world space to cone space.
  590. X     */
  591. X/*    if (equal(axis.z*axis.z, 1.)) {
  592. X        tmp.x = 0.;
  593. X        tmp.y = -axis.z;
  594. X        tmp.z = 0.;
  595. X    } else { */
  596. X        tmp.x = axis.y;
  597. X        tmp.y = -axis.x;
  598. X        tmp.z = 0.;
  599. X    /*} */
  600. X    rotate(trans, &tmp, acos(axis.z));
  601. X    translate(trans, &base);
  602. X    cone->tantheta *= cone->tantheta;
  603. X
  604. X    return newobj;
  605. X}
  606. X
  607. X/*
  608. X * Ray-cone intersection test.  This routine is far from optimal, but
  609. X * it's straight-forward and it works...
  610. X */
  611. Xdouble
  612. Xintcone(pos, ray, obj)
  613. XVector           *pos, *ray;
  614. XPrimitive       *obj;
  615. X{
  616. X    double t1, t2, a, b, c, disc, zpos, et1, et2;
  617. X    double x, y;
  618. X    extern unsigned long primtests[];
  619. X    Cone *cone;
  620. X
  621. X    primtests[CONE]++;
  622. X    cone = obj->objpnt.p_cone;
  623. X
  624. X    /*
  625. X     * Recall that 'tantheta' is really tantheta^2.
  626. X     */
  627. X    a = ray->x * ray->x + ray->y * ray->y - ray->z*ray->z*cone->tantheta;
  628. X    b = ray->x * pos->x + ray->y * pos->y - cone->tantheta*ray->z*pos->z;
  629. X    c = pos->x*pos->x + pos->y*pos->y - cone->tantheta*pos->z*pos->z;
  630. X
  631. X    if (equal(a, 0.)) {
  632. X        /*
  633. X         * Only one intersection point...
  634. X         */
  635. X        t1 = -c / b;
  636. X        zpos = pos->z + t1 * ray->z;
  637. X        if (t1 < EPSILON || zpos < cone->start_pos ||
  638. X            zpos > cone->end_pos)
  639. X            t1 = FAR_AWAY;
  640. X        t2 = FAR_AWAY;
  641. X    } else {
  642. X        disc = b*b - a*c;
  643. X        if(disc < 0.)
  644. X            return 0.;        /* No possible intersection */
  645. X        disc = sqrt(disc);
  646. X        t1 = (-b + disc) / a;
  647. X        t2 = (-b - disc) / a;
  648. X        /*
  649. X         * Clip intersection points.
  650. X         */
  651. X        zpos = pos->z + t1 * ray->z;
  652. X        if (t1 < EPSILON || zpos < cone->start_pos ||
  653. X            zpos > cone->end_pos)
  654. X            t1 = FAR_AWAY;
  655. X        zpos = pos->z + t2 * ray->z;
  656. X        if (t2 < EPSILON || zpos < cone->start_pos ||
  657. X            zpos > cone->end_pos)
  658. X            t2 = FAR_AWAY;
  659. X    }
  660. X    /*
  661. X     * Find t for both endcaps.
  662. X     */
  663. X    et1 = (cone->start_pos - pos->z) / ray->z;
  664. X    x = pos->x + et1 * ray->x;
  665. X    y = pos->y + et1 * ray->y;
  666. X    if (x*x + y*y > cone->start_pos*cone->start_pos*cone->tantheta)
  667. X        et1 = FAR_AWAY;
  668. X    et2 = (cone->end_pos - pos->z) / ray->z;
  669. X    x = pos->x + et2 * ray->x;
  670. X    y = pos->y + et2 * ray->y;
  671. X    if (x*x + y*y > cone->end_pos*cone->end_pos*cone->tantheta)
  672. X        et2 = FAR_AWAY;
  673. X
  674. X    t1 = min(t1, min(t2, min(et1, et2)));
  675. X    return (t1 == FAR_AWAY ? 0. : t1);
  676. X}
  677. X
  678. X/*
  679. X * Compute the normal to a cone at a given location on its surface.
  680. X */
  681. Xnrmcone(pos, obj, nrm)
  682. XVector *pos, *nrm;
  683. XPrimitive *obj;
  684. X{
  685. X    Cone *cone;
  686. X
  687. X    cone = obj->objpnt.p_cone;
  688. X
  689. X    if (equal(pos->z, cone->start_pos)) {
  690. X        nrm->x = nrm->y = 0.;
  691. X        nrm->z = -1.;
  692. X    } else if (equal(pos->z, cone->end_pos)) {
  693. X        nrm->x = nrm->y = 0.;
  694. X        nrm->z = 1.;
  695. X    } else {
  696. X        /*
  697. X         * The following is equal to
  698. X         * (pos X (0, 0, 1)) X pos
  699. X         */
  700. X        nrm->x = pos->x * pos->z;
  701. X        nrm->y = pos->y * pos->z;
  702. X        nrm->z = -pos->x * pos->x - pos->y * pos->y;
  703. X    }
  704. X}
  705. X
  706. X/*
  707. X * Return the extent of a cone.
  708. X */
  709. Xconeextent(o, bounds)
  710. XPrimitive *o;
  711. Xdouble bounds[2][3];
  712. X{
  713. X    Cone *cone;
  714. X
  715. X    cone = o->objpnt.p_cone;
  716. X
  717. X    bounds[LOW][X] = bounds[LOW][Y] = -cone->apex_rad;
  718. X    bounds[HIGH][X] = bounds[HIGH][Y] = cone->apex_rad;
  719. X    bounds[LOW][Z] = cone->start_pos;
  720. X    bounds[HIGH][Z] = cone->end_pos;
  721. X}
  722. END_OF_FILE
  723. if test 6421 -ne `wc -c <'src/cone.c'`; then
  724.     echo shar: \"'src/cone.c'\" unpacked with wrong size!
  725. fi
  726. # end of 'src/cone.c'
  727. fi
  728. if test -f 'src/cylinder.c' -a "${1}" != "-c" ; then 
  729.   echo shar: Will not clobber existing file \"'src/cylinder.c'\"
  730. else
  731. echo shar: Extracting \"'src/cylinder.c'\" \(4819 characters\)
  732. sed "s/^X//" >'src/cylinder.c' <<'END_OF_FILE'
  733. X/*
  734. X * cylinder.c
  735. X *
  736. X * Copyright (C) 1989, Craig E. Kolb
  737. X *
  738. X * This software may be freely copied, modified, and redistributed,
  739. X * provided that this copyright notice is preserved on all copies.
  740. X *
  741. X * There is no warranty or other guarantee of fitness for this software,
  742. X * it is provided solely .  Bug reports or fixes may be sent
  743. X * to the author, who may or may not act on them as he desires.
  744. X *
  745. X * You may not include this software in a program or other software product
  746. X * without supplying the source, or without informing the end-user that the
  747. X * source is available for no extra charge.
  748. X *
  749. X * If you modify this software, you should include a notice giving the
  750. X * name of the person performing the modification, the date of modification,
  751. X * and the reason for such modification.
  752. X *
  753. X * $Id: cylinder.c,v 3.0 89/10/27 02:05:48 craig Exp $
  754. X *
  755. X * $Log:    cylinder.c,v $
  756. X * Revision 3.0  89/10/27  02:05:48  craig
  757. X * Baseline for first official release.
  758. X * 
  759. X */
  760. X#include <stdio.h>
  761. X#include <math.h>
  762. X#include "typedefs.h"
  763. X#include "funcdefs.h"
  764. X#include "constants.h"
  765. X
  766. XObject *
  767. Xmakcyl(surf, cent, ax, r, trans)
  768. Xchar *surf;
  769. XVector *cent, *ax;
  770. Xdouble r;
  771. XTransInfo *trans;
  772. X{
  773. X    Cylinder *cyl;
  774. X    Primitive *prim;
  775. X    Object *newobj;
  776. X    double len;
  777. X    extern int yylineno, Quiet;
  778. X    Vector axis, dir;
  779. X
  780. X    if (r <= 0.) {
  781. X        if (!Quiet)
  782. X            fprintf(stderr,"Invalid cylinder radius (line %d)\n",
  783. X                yylineno);
  784. X        return (Object *)0;
  785. X    }
  786. X
  787. X    prim = mallocprim();
  788. X    newobj = new_object(NULL, CYL, (char *)prim, (Trans *)NULL);
  789. X    prim->surf = find_surface(surf);
  790. X    prim->type = CYL;
  791. X    cyl = (Cylinder *)Malloc(sizeof(Cylinder));
  792. X    prim->objpnt.p_cylinder = cyl;
  793. X
  794. X    axis.x = ax->x - cent->x;
  795. X    axis.y = ax->y - cent->y;
  796. X    axis.z = ax->z - cent->z;
  797. X
  798. X    len = normalize(&axis);
  799. X    if(len < EPSILON) {
  800. X        if (!Quiet)
  801. X            fprintf(stderr,"Degenerate cylinder (line %d).\n",
  802. X                            yylineno);
  803. X        free((char *)cyl);
  804. X        free((char *)prim);
  805. X        return (Object *)0;
  806. X    }
  807. X
  808. X    cyl->rad = r*r;
  809. X    cyl->len = len;
  810. X    /*
  811. X     * Define matrix to transform from axis-aligned to desired cylinder.
  812. X     */
  813. X    dir.x = axis.y;
  814. X    dir.y = -axis.x;
  815. X    dir.z = 0.;
  816. X    rotate(trans, &dir, acos(axis.z));
  817. X    translate(trans, cent);
  818. X
  819. X    return newobj;
  820. X}
  821. X
  822. X/*
  823. X * Ray-cylinder intersection test.
  824. X */
  825. Xdouble
  826. Xintcyl(pos, ray, obj)
  827. XVector           *pos, *ray;
  828. XPrimitive       *obj;
  829. X{
  830. X    double t1, t2, a, b, c, zpos1, zpos2, et1, et2, x, y, disc;
  831. X    extern unsigned long primtests[];
  832. X    Cylinder *cyl;
  833. X
  834. X    primtests[CYL]++;
  835. X    cyl = obj->objpnt.p_cylinder;
  836. X
  837. X    a = ray->x * ray->x + ray->y * ray->y;
  838. X    c = pos->x*pos->x + pos->y*pos->y - cyl->rad;
  839. X
  840. X    if (a < EPSILON*EPSILON) {    /* |ray->z| == 1. */
  841. X        if(c < EPSILON*EPSILON)    /* Within endcap */
  842. X            /* Wrong if origin is inside cylinder. */
  843. X            return min(-pos->z / ray->z,
  844. X                  (cyl->len - pos->z) / ray->z);
  845. X        return 0.;
  846. X    }
  847. X
  848. X    b = ray->x * pos->x + ray->y * pos->y;
  849. X    disc = b*b - a*c;
  850. X    if(disc < 0.)
  851. X        return 0.;
  852. X    disc = sqrt(disc);
  853. X    t1 = (-b + disc) / a;
  854. X    t2 = (-b - disc) / a;
  855. X    if(t1 < EPSILON && t2 < EPSILON)
  856. X        return 0.;
  857. X    zpos1 = pos->z + t1 * ray->z;
  858. X    zpos2 = pos->z + t2 * ray->z;
  859. X    if ((zpos1 > cyl->len && zpos2 > cyl->len) ||
  860. X        (zpos1 < 0. && zpos2 < 0.))
  861. X        return 0.;
  862. X    if (t1 < EPSILON)
  863. X        t1 = FAR_AWAY;
  864. X    if (t2 < EPSILON)
  865. X        t2 = FAR_AWAY;
  866. X    if (t1 == FAR_AWAY && t2 == FAR_AWAY)
  867. X        return 0.;
  868. X    /*
  869. X     * Don't bother checking endcaps if both intersection points
  870. X     * are on the cylinder.
  871. X     */
  872. X    if ((zpos1 > 0. && zpos1 < cyl->len && zpos2 > 0. && zpos2 < cyl->len))
  873. X        return min(t1, t2);
  874. X    /*
  875. X      * It's possible to get rid of the ray-disc intersection tests
  876. X     * (by looking at t1, t2 and zpos1, zpos), but the code gets messy.
  877. X     */
  878. X    if (zpos1 < 0. || zpos1 > cyl->len)
  879. X        t1 = FAR_AWAY;
  880. X    if (zpos2 < 0. || zpos2 > cyl->len)
  881. X        t2 = FAR_AWAY;
  882. X    et1 = -pos->z / ray->z;
  883. X    x = pos->x + et1 * ray->x;
  884. X    y = pos->y + et1 * ray->y;
  885. X    if (x*x + y*y > cyl->rad)
  886. X        et1 = FAR_AWAY;
  887. X    et2 = (cyl->len - pos->z) / ray->z;
  888. X    x = pos->x + et2 * ray->x;
  889. X    y = pos->y + et2 * ray->y;
  890. X    if (x*x + y*y > cyl->rad)
  891. X        et2 = FAR_AWAY;
  892. X    t1 = min(t1, min(t2, min(et1, et2)));
  893. X    return (t1 == FAR_AWAY ? 0. : t1);
  894. X}
  895. X
  896. Xnrmcyl(pos, obj, nrm)
  897. XVector *pos, *nrm;
  898. XPrimitive *obj;
  899. X{
  900. X    Cylinder *cyl;
  901. X    double dist;
  902. X
  903. X    cyl = obj->objpnt.p_cylinder;
  904. X
  905. X    dist = pos->x*pos->x + pos->y*pos->y;
  906. X    if (dist+EPSILON < cyl->rad) {
  907. X        if (equal(pos->z,0.)) {
  908. X            /*
  909. X             * Hit on lower endcap.
  910. X             */
  911. X            nrm->x = nrm->y = 0.;
  912. X            nrm->z = -1.;
  913. X        } else {
  914. X            /*
  915. X             * Hit on upper endcap.
  916. X             */
  917. X            nrm->x = nrm->y = 0.;
  918. X            nrm->z = 1.;
  919. X        }
  920. X    } else {    /* Hit along cylinder. */
  921. X        nrm->x = pos->x;
  922. X        nrm->y = pos->y;
  923. X        nrm->z = 0.;
  924. X        /* Will be normalized by ShadeRay(). */
  925. X    }
  926. X}
  927. X
  928. Xcylextent(o, bounds)
  929. XPrimitive *o;
  930. Xdouble bounds[2][3];
  931. X{
  932. X    Cylinder *cyl;
  933. X    double r;
  934. X    cyl = o->objpnt.p_cylinder;
  935. X
  936. X    r = sqrt(cyl->rad);
  937. X    bounds[LOW][X] = bounds[LOW][Y] = -r;
  938. X    bounds[HIGH][X] = bounds[HIGH][Y] = r;
  939. X    bounds[LOW][Z] = 0.;
  940. X    bounds[HIGH][Z] = cyl->len;
  941. X}
  942. END_OF_FILE
  943. if test 4819 -ne `wc -c <'src/cylinder.c'`; then
  944.     echo shar: \"'src/cylinder.c'\" unpacked with wrong size!
  945. fi
  946. # end of 'src/cylinder.c'
  947. fi
  948. if test -f 'src/intersect.c' -a "${1}" != "-c" ; then 
  949.   echo shar: Will not clobber existing file \"'src/intersect.c'\"
  950. else
  951. echo shar: Extracting \"'src/intersect.c'\" \(6514 characters\)
  952. sed "s/^X//" >'src/intersect.c' <<'END_OF_FILE'
  953. X/*
  954. X * intersect.c
  955. X *
  956. X * Copyright (C) 1989, Craig E. Kolb
  957. X *
  958. X * This software may be freely copied, modified, and redistributed,
  959. X * provided that this copyright notice is preserved on all copies.
  960. X *
  961. X * There is no warranty or other guarantee of fitness for this software,
  962. X * it is provided solely .  Bug reports or fixes may be sent
  963. X * to the author, who may or may not act on them as he desires.
  964. X *
  965. X * You may not include this software in a program or other software product
  966. X * without supplying the source, or without informing the end-user that the
  967. X * source is available for no extra charge.
  968. X *
  969. X * If you modify this software, you should include a notice giving the
  970. X * name of the person performing the modification, the date of modification,
  971. X * and the reason for such modification.
  972. X *
  973. X * $Id: intersect.c,v 3.0 89/10/27 02:05:53 craig Exp $
  974. X *
  975. X * $Log:    intersect.c,v $
  976. X * Revision 3.0  89/10/27  02:05:53  craig
  977. X * Baseline for first official release.
  978. X * 
  979. X */
  980. X#include <math.h>
  981. X#include <stdio.h>
  982. X#include "typedefs.h"
  983. X#include "funcdefs.h"
  984. X#include "constants.h"
  985. X
  986. X/*
  987. X * Primitive intersection routines
  988. X */
  989. Xdouble (*objint[])() = {intsph, intbox, inttri, intsup, intplane, intcyl,
  990. X            intpoly, inttri, intcone, inthf};
  991. X/*
  992. X * Primitive normal routines
  993. X */
  994. Xint (*objnrm[])() = {nrmsph, nrmbox, nrmtri, nrmsup, nrmplane, nrmcyl,
  995. X            nrmpoly, nrmtri, nrmcone, nrmhf};
  996. X/*
  997. X * object extent box routines
  998. X */
  999. Xint (*objextent[])() = {sphextent, boxextent, triextent, supextent,
  1000. X            planeextent, cylextent, polyextent, triextent,
  1001. X            coneextent, hfextent};
  1002. X
  1003. Xunsigned long int primtests[PRIMTYPES], primhits[PRIMTYPES];
  1004. X
  1005. Xchar *primnames[PRIMTYPES] = {  "Sphere", "Box", "Triangle", "Superq", "Plane",
  1006. X                "Cylinder", "Polygon", "Phongtri", "Cone",
  1007. X                "Heightfield"};
  1008. X
  1009. X/*
  1010. X * Flags indicating whether or not we should check for intersection
  1011. X * with an object's bounding box before we check for intersection
  1012. X * with the object.
  1013. X */
  1014. Xchar CheckBounds[] = {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE,
  1015. X            TRUE, FALSE, FALSE, FALSE};
  1016. X
  1017. X/*
  1018. X * Top-level raytracing routine.  Increment ray number, initialize
  1019. X * intersection information and trace ray through "World" object.
  1020. X */
  1021. Xdouble
  1022. XTraceRay(source, ray, hitinfo)
  1023. XPrimitive *source;
  1024. XRay *ray;
  1025. XHitInfo *hitinfo;
  1026. X{
  1027. X    extern Object *World;
  1028. X    extern double intersect();
  1029. X
  1030. X    return intersect(World, source, ray, hitinfo);
  1031. X}
  1032. X
  1033. X/*
  1034. X * Intersect object & ray.  Return distance from "pos" along "ray" to
  1035. X * intersection point.  Return value <= 0 indicates no intersection.
  1036. X */
  1037. Xdouble
  1038. Xintersect(obj, source, ray, hitinfo)
  1039. XObject *obj;                /* Object to be tested. */
  1040. XPrimitive *source;            /* Prim, if any, that pos is on. */
  1041. XRay *ray;                /* Ray origin, direction. */
  1042. XHitInfo *hitinfo;            /* Data on intersection (pos, norm) */
  1043. X{
  1044. X    Ray newray;
  1045. X    double dist, distfact, TransformRay();
  1046. X    extern int Cache;
  1047. X
  1048. X    /*
  1049. X     * Check ray/bounding volume intersection, if required.
  1050. X     */
  1051. X    if (CheckBounds[obj->type] &&
  1052. X        OutOfBounds(&ray->pos, obj->bounds) &&
  1053. X        IntBounds(ray, obj->bounds) < EPSILON)
  1054. X            return 0.;
  1055. X
  1056. X    newray = *ray;
  1057. X
  1058. X    /*
  1059. X     * Transform the ray if necessary.
  1060. X     */
  1061. X    if (obj->trans != (Trans *)0) {
  1062. X        /*
  1063. X         * Transforming the ray can change the distance between
  1064. X         * the ray origin and the point of intersection.
  1065. X         * We save the amount the ray is "stretched" and later
  1066. X         * divide the computed distance by this amount.
  1067. X         */
  1068. X        distfact = TransformRay(&newray, &obj->trans->world2obj);
  1069. X    }
  1070. X
  1071. X    /*
  1072. X     * Call correct intersection routine.
  1073. X     */
  1074. X    if (obj->type == GRID)
  1075. X        dist = int_grid((Grid *)obj->data, source, &newray, hitinfo);
  1076. X    else if (obj->type == LIST)
  1077. X        dist = int_list((List *)obj->data, source, &newray, hitinfo);
  1078. X    else
  1079. X        dist = int_primitive((Primitive *)obj->data, source, &newray,
  1080. X                    hitinfo);
  1081. X
  1082. X    if (dist < EPSILON)
  1083. X        return 0.;
  1084. X
  1085. X    /*
  1086. X     * If this is a shadow ray, don't bother with texture mapping
  1087. X     * or transformation of normal.
  1088. X     */
  1089. X    if (ray->shadow) {
  1090. X        if (obj->trans == (Trans *)0)
  1091. X            return dist;
  1092. X        else if (Cache)
  1093. X            /*
  1094. X              * Keep track of total transformation applied to ray
  1095. X              * if necessary.
  1096. X              */
  1097. X            mmult(hitinfo->totaltrans, &obj->trans->world2obj,
  1098. X                hitinfo->totaltrans);
  1099. X        return dist / distfact;
  1100. X    }
  1101. X    /*
  1102. X     * Perform texture mapping.
  1103. X     */
  1104. X    if (obj->texture)
  1105. X        apply_textures(hitinfo, obj->texture);
  1106. X
  1107. X    if (obj->trans) {
  1108. X        /*
  1109. X         * Transform hitinfo structure.  As things stand,
  1110. X         * this just means transforming the normal and
  1111. X         * dividing "dist" by the amount the ray was
  1112. X         * stretched.
  1113. X         */
  1114. X        dist /= distfact;
  1115. X        TransformNormal(&hitinfo->norm, &obj->trans->world2obj);
  1116. X    }
  1117. X
  1118. X    return dist;
  1119. X}
  1120. X
  1121. X/*
  1122. X * Intersect ray & primitive object.
  1123. X */
  1124. Xdouble
  1125. Xint_primitive(prim, source, ray, hitinfo)
  1126. XPrimitive *prim, *source;
  1127. XRay *ray;
  1128. XHitInfo *hitinfo;
  1129. X{
  1130. X    double dist;
  1131. X
  1132. X    if (prim == source && prim->type != HF)
  1133. X        /*
  1134. X         * Don't check for intersection with "source", unless
  1135. X         * source is a height field.  (Height fields may shadow
  1136. X         * themselves.)
  1137. X         */
  1138. X        return 0.;
  1139. X
  1140. X    dist = (*objint[prim->type]) (&ray->pos, &ray->dir, prim);
  1141. X
  1142. X    if (dist < EPSILON)
  1143. X        return 0.;
  1144. X
  1145. X    primhits[prim->type]++;
  1146. X    hitinfo->prim = prim;
  1147. X    hitinfo->surf = *prim->surf;
  1148. X
  1149. X    if (ray->shadow)
  1150. X        return dist;    /* If a shadow ray, don't bother with normal */
  1151. X    /*
  1152. X     * Calculate point of intersection in object space.
  1153. X      * (The point of intersection in world space is
  1154. X     * calculated in ShadeRay().)
  1155. X     */
  1156. X    addscaledvec(ray->pos, dist, ray->dir, &hitinfo->pos);
  1157. X
  1158. X    /*
  1159. X     * Find normal to primitive.
  1160. X     */
  1161. X    (*objnrm[prim->type]) (&hitinfo->pos, prim, &hitinfo->norm);
  1162. X
  1163. X    /*
  1164. X     * Make sure normal points towards ray origin.  If surface is
  1165. X     * transparent, keep as-is, as the normal indicates whether we're
  1166. X     * entering or exiting.  If the prim is a superquadric, don't flip,
  1167. X     * as this leads to strange edge effects.
  1168. X     */
  1169. X    if (dotp(&ray->dir, &hitinfo->norm) > 0 && hitinfo->surf.transp == 0. &&
  1170. X        prim->type != SUPERQ) {
  1171. X        scalar_prod(-1., hitinfo->norm, &hitinfo->norm);
  1172. X    }
  1173. X
  1174. X    return dist;
  1175. X}
  1176. X
  1177. Xprint_prim_stats()
  1178. X{
  1179. X    long int totaltests, totalhits;
  1180. X    extern FILE *fstats;
  1181. X    int i;
  1182. X
  1183. X    totaltests = totalhits = 0;
  1184. X    for (i = 0; i < PRIMTYPES; i++) {
  1185. X        if (primtests[i] == 0)
  1186. X            continue;
  1187. X        fprintf(fstats,"%s intersection tests:\t%ld (%ld hit, %f%%)\n",
  1188. X                primnames[i], primtests[i],
  1189. X                primhits[i],
  1190. X                100.*(float)primhits[i]/(float)primtests[i]);
  1191. X        totaltests += primtests[i];
  1192. X        totalhits += primhits[i];
  1193. X    }
  1194. X    fprintf(fstats,"Total intersection tests:\t%ld", totaltests);
  1195. X    if (totaltests == 0)
  1196. X        fprintf(fstats,"\n");
  1197. X    else
  1198. X        fprintf(fstats," (%ld hit, %f%%)\n", totalhits,
  1199. X            100.*(float)totalhits/(float)totaltests);
  1200. X}
  1201. END_OF_FILE
  1202. if test 6514 -ne `wc -c <'src/intersect.c'`; then
  1203.     echo shar: \"'src/intersect.c'\" unpacked with wrong size!
  1204. fi
  1205. # end of 'src/intersect.c'
  1206. fi
  1207. if test -f 'src/light.c' -a "${1}" != "-c" ; then 
  1208.   echo shar: Will not clobber existing file \"'src/light.c'\"
  1209. else
  1210. echo shar: Extracting \"'src/light.c'\" \(5124 characters\)
  1211. sed "s/^X//" >'src/light.c' <<'END_OF_FILE'
  1212. X/*
  1213. X * light.c
  1214. X *
  1215. X * Copyright (C) 1989, Craig E. Kolb
  1216. X *
  1217. X * This software may be freely copied, modified, and redistributed,
  1218. X * provided that this copyright notice is preserved on all copies.
  1219. X *
  1220. X * There is no warranty or other guarantee of fitness for this software,
  1221. X * it is provided solely .  Bug reports or fixes may be sent
  1222. X * to the author, who may or may not act on them as he desires.
  1223. X *
  1224. X * You may not include this software in a program or other software product
  1225. X * without supplying the source, or without informing the end-user that the
  1226. X * source is available for no extra charge.
  1227. X *
  1228. X * If you modify this software, you should include a notice giving the
  1229. X * name of the person performing the modification, the date of modification,
  1230. X * and the reason for such modification.
  1231. X *
  1232. X * $Id: light.c,v 3.0 89/10/27 16:17:22 craig Exp $
  1233. X *
  1234. X * $Log:    light.c,v $
  1235. X * Revision 3.0  89/10/27  16:17:22  craig
  1236. X * Baseline for first official release.
  1237. X * 
  1238. X */
  1239. X#include <stdio.h>
  1240. X#include <math.h>
  1241. X#include "typedefs.h"
  1242. X#include "funcdefs.h"
  1243. X#include "constants.h"
  1244. X
  1245. Xint    nlight;            /* # of lights defined */
  1246. Xint    NoShadows;        /* Don't trace shadow rays */
  1247. Xint    Cache = TRUE;        /* Use shadow-caching */
  1248. Xint    ClearShadows;        /* Shadow rays pass through transp. objects */
  1249. XLight    light[LIGHTS];        /* array of lights */
  1250. Xdouble    lightdist;        /* distance to light */
  1251. Xunsigned long CacheWorked, CacheFailed, ShadowHits;
  1252. X/*
  1253. X * Calculate ray from position to light # lnum.
  1254. X */
  1255. Xlightray(lp, objpos, lray)
  1256. XLight *lp;
  1257. XVector *objpos, *lray;
  1258. X{
  1259. X    if(lp->type == DIRECTIONAL) {
  1260. X        /*
  1261. X         * Directional sources only have direction.
  1262. X         */
  1263. X        *lray = lp->pos;
  1264. X        lightdist = FAR_AWAY;
  1265. X    } else {
  1266. X        /*
  1267. X         * Calculate ray from position to center of
  1268. X         * light source.
  1269. X         */
  1270. X        vecsub(lp->pos, *objpos, lray);
  1271. X        lightdist = normalize(lray);
  1272. X    }
  1273. X}
  1274. X
  1275. X/*
  1276. X * Find a coordinate system perpendicular to the ray from
  1277. X * a point of intersection to the center of an extended light source.
  1278. X */
  1279. XLightCoordSys(lp, pos, vector, xaxis, yaxis)
  1280. XLight *lp;
  1281. XVector *pos, *vector, *xaxis, *yaxis;
  1282. X{
  1283. X    /*
  1284. X     * Vector should *not* be normalized, xaxis & yaxis should be.
  1285. X     */
  1286. X    vector->x = lp->pos.x - pos->x;
  1287. X    vector->y = lp->pos.y - pos->y;
  1288. X    vector->z = lp->pos.z - pos->z;
  1289. X    xaxis->x = vector->y;
  1290. X    xaxis->y = -vector->x;
  1291. X    xaxis->z = 0.;
  1292. X    if (normalize(xaxis) == 0.) {
  1293. X        xaxis->x = 0.;
  1294. X        xaxis->y = -vector->z;
  1295. X        xaxis->z = vector->y;
  1296. X        if (normalize(xaxis) == 0.)
  1297. X            fprintf(stderr,"LightCoordSys: Can't find X axis!\n");
  1298. X        yaxis->x = (vector->y * vector->y) + (vector->z * vector->z);
  1299. X        yaxis->y = -vector->x * vector->y;
  1300. X        yaxis->z = -vector->x * vector->z;
  1301. X        (void)normalize(yaxis);
  1302. X    } else {
  1303. X        yaxis->x = vector->x * vector->z;
  1304. X        yaxis->y = vector->y * vector->z;
  1305. X        yaxis->z = -(vector->x * vector->x) -(vector->y * vector->y);
  1306. X        (void)normalize(yaxis);
  1307. X    }
  1308. X}
  1309. X
  1310. X/*
  1311. X * Trace ray from point of intersection to a light.  If an intersection
  1312. X * occurs at a distance less than "lightdist" (the distance to the
  1313. X * light source), then the point is in shadow, and 0 is returned.
  1314. X * Otherwise, the brightness (color) of the light is returned.  This
  1315. X * color may be modulated by any translucent objects which fall between
  1316. X * the point of intersection and the light source.
  1317. X */
  1318. Xinshadow(result, source, lp, pos, ray)
  1319. XColor *result;
  1320. XPrimitive *source;
  1321. XLight *lp;
  1322. XVector *pos, *ray;
  1323. X{
  1324. X    double s;
  1325. X    Ray tmpray, tray;
  1326. X    HitInfo hitinfo;
  1327. X    double atten, totaldist, TransformRay();
  1328. X    extern int level;
  1329. X    extern unsigned long ShadowRays;
  1330. X    extern double TraceRay();
  1331. X
  1332. X    if (NoShadows) {
  1333. X        *result = lp->color;
  1334. X        return FALSE;
  1335. X    }
  1336. X
  1337. X    ShadowRays++;
  1338. X    tmpray.pos = *pos;
  1339. X    tmpray.dir = *ray;    /* Medium not needed. */
  1340. X    tmpray.shadow = TRUE;
  1341. X    hitinfo.totaltrans = &lp->trans[level];
  1342. X
  1343. X    /*
  1344. X     * Check shadow cache if necessary.  (The following implies
  1345. X     * ... && Cache)
  1346. X     */
  1347. X    if (lp->cache[level]) {
  1348. X        tray = tmpray;
  1349. X        s = TransformRay(&tray, &lp->trans[level]);
  1350. X        s = int_primitive(lp->cache[level], source, &tray, &hitinfo)/s;
  1351. X        if (s > EPSILON && s < lightdist) {
  1352. X            CacheWorked++;
  1353. X            return TRUE;
  1354. X        }
  1355. X        CacheFailed++;
  1356. X        lp->cache[level] = (Primitive *)0;
  1357. X    }
  1358. X
  1359. X    if (Cache)
  1360. X        init_trans(hitinfo.totaltrans);
  1361. X
  1362. X    s = TraceRay(source, &tmpray, &hitinfo);
  1363. X
  1364. X    if (s < EPSILON || s > lightdist) {
  1365. X        *result = lp->color;
  1366. X        return FALSE;        /* Not in shadow. */
  1367. X    }
  1368. X
  1369. X    /*
  1370. X     * Otherwise, we've hit something.
  1371. X     */
  1372. X    ShadowHits++;
  1373. X    if (!ClearShadows || hitinfo.surf.transp == 0.) {
  1374. X        if (Cache)
  1375. X            lp->cache[level] = hitinfo.prim;
  1376. X        return TRUE;
  1377. X    }
  1378. X    /*
  1379. X     * We've hit a transparent object.  Attenuate the color
  1380. X     * of the light source and continue the ray until
  1381. X     * we hit background or a non-transparent object.
  1382. X     * Note that this is incorrect if any of the surfaces hit (or
  1383. X     * DefIndex) have differing indices of refraction.
  1384. X     */
  1385. X    atten = 1.;
  1386. X    totaldist = s;
  1387. X    do {
  1388. X        atten *= hitinfo.surf.transp;
  1389. X        if (atten < EPSILON)
  1390. X            return TRUE;
  1391. X        addscaledvec(tmpray.pos, s, tmpray.dir, &tmpray.pos);
  1392. X        /*
  1393. X         * Trace ray starting at new origin and in the
  1394. X         * same direction.
  1395. X         */
  1396. X        s = TraceRay(hitinfo.prim, &tmpray, &hitinfo);
  1397. X        totaldist += s;
  1398. X    } while (s > EPSILON && totaldist < lightdist);
  1399. X
  1400. X    ScaleColor(atten, lp->color, result);
  1401. X    return FALSE;
  1402. X}
  1403. END_OF_FILE
  1404. if test 5124 -ne `wc -c <'src/light.c'`; then
  1405.     echo shar: \"'src/light.c'\" unpacked with wrong size!
  1406. fi
  1407. # end of 'src/light.c'
  1408. fi
  1409. if test -f 'src/object.c' -a "${1}" != "-c" ; then 
  1410.   echo shar: Will not clobber existing file \"'src/object.c'\"
  1411. else
  1412. echo shar: Extracting \"'src/object.c'\" \(4915 characters\)
  1413. sed "s/^X//" >'src/object.c' <<'END_OF_FILE'
  1414. X/*
  1415. X * object.c
  1416. X *
  1417. X * Copyright (C) 1989, Craig E. Kolb
  1418. X *
  1419. X * This software may be freely copied, modified, and redistributed,
  1420. X * provided that this copyright notice is preserved on all copies.
  1421. X *
  1422. X * There is no warranty or other guarantee of fitness for this software,
  1423. X * it is provided solely .  Bug reports or fixes may be sent
  1424. X * to the author, who may or may not act on them as he desires.
  1425. X *
  1426. X * You may not include this software in a program or other software product
  1427. X * without supplying the source, or without informing the end-user that the
  1428. X * source is available for no extra charge.
  1429. X *
  1430. X * If you modify this software, you should include a notice giving the
  1431. X * name of the person performing the modification, the date of modification,
  1432. X * and the reason for such modification.
  1433. X *
  1434. X * $Id: object.c,v 3.0 89/10/27 02:05:58 craig Exp $
  1435. X *
  1436. X * $Log:    object.c,v $
  1437. X * Revision 3.0  89/10/27  02:05:58  craig
  1438. X * Baseline for first official release.
  1439. X * 
  1440. X */
  1441. X#include <stdio.h>
  1442. X#include <math.h>
  1443. X#include "constants.h"
  1444. X#include "typedefs.h"
  1445. X#include "funcdefs.h"
  1446. X#include "texture.h"
  1447. X
  1448. XObject *World;            /* World Object */
  1449. XObjList *Objects;        /* Linked list of defined objects */
  1450. Xint WorldXSize, WorldYSize, WorldZSize;        /* World grid resolution */
  1451. X
  1452. X/*
  1453. X * Create a new object with the given properties.
  1454. X */
  1455. XObject *
  1456. Xnew_object(name, type, data, trans)
  1457. Xchar *name, *data;
  1458. Xchar type;
  1459. XTrans *trans;
  1460. X{
  1461. X    Object *new;
  1462. X
  1463. X    new = (Object *)share_malloc(sizeof(Object));
  1464. X    new->name = strsave(name);
  1465. X    new->type = type;
  1466. X    new->data = data;
  1467. X    new->trans = trans;
  1468. X#ifdef LINDA
  1469. X    /*
  1470. X     * If the counter is in shared memory, processes will
  1471. X     * be modifying it left-and-right.  So, we cheat and
  1472. X     * make counter a pointer to a non-shared location and
  1473. X     * store the value there.
  1474. X     */
  1475. X    new->counter = (unsigned long *)malloc(sizeof(unsigned long));
  1476. X    *new->counter = 0;
  1477. X#else
  1478. X    new->counter = 0;
  1479. X#endif
  1480. X    new->texture = (Texture *)0;
  1481. X    /*
  1482. X     * bounds is left uninitialized.
  1483. X     */
  1484. X    return new;
  1485. X}
  1486. X
  1487. X/*
  1488. X * Add a copy of the named object to parent object
  1489. X */
  1490. XObject *
  1491. Xadd_child_named(name, parent)
  1492. Xchar *name;
  1493. XObject *parent;
  1494. X{
  1495. X    Object *child, *newobj;
  1496. X    int i;
  1497. X
  1498. X    child = get_object_named(name);
  1499. X    if (child == (Object *)0) {
  1500. X        fprintf(stderr,"There is no object named \"%s\".\n",name);
  1501. X        exit(1);
  1502. X    }
  1503. X    /*
  1504. X     * Create new object that points to child
  1505. X     * and add to 'parent' list.
  1506. X     */
  1507. X    newobj = add_child(child, parent);
  1508. X    /*
  1509. X     * New object's bounding box is initally the same
  1510. X     * as the child's.
  1511. X     */
  1512. X    for (i = 0; i < 3; i++) {
  1513. X        newobj->bounds[0][i] = child->bounds[0][i];
  1514. X        newobj->bounds[1][i] = child->bounds[1][i];
  1515. X    }
  1516. X    return newobj;
  1517. X}
  1518. X
  1519. X/*
  1520. X * Add primitive object to parent object.
  1521. X */
  1522. Xadd_prim(child, parent)
  1523. XObject *child, *parent;
  1524. X{
  1525. X    ObjList *newnode;
  1526. X
  1527. X    newnode = (ObjList *)share_malloc(sizeof(ObjList));
  1528. X    newnode->data = child;
  1529. X    if (parent == (Object *)0) {
  1530. X        newnode->next = (ObjList *)World->data;
  1531. X        World->data = (char *)newnode;
  1532. X    } else {
  1533. X        newnode->next = (ObjList *)parent->data;
  1534. X        parent->data = (char *)newnode;
  1535. X    }
  1536. X}
  1537. X
  1538. X/*
  1539. X * Make a copy of "child" and attach it to parent's linked list
  1540. X * of objects.
  1541. X */
  1542. XObject *
  1543. Xadd_child(child, parent)
  1544. XObject *child, *parent;
  1545. X{
  1546. X    Object *newobj;
  1547. X    ObjList *newnode;
  1548. X
  1549. X    newobj = new_object(NULL, child->type, child->data, child->trans);
  1550. X    newobj->texture = child->texture;
  1551. X    newnode = (ObjList *)share_malloc(sizeof(ObjList));
  1552. X    newnode->data = newobj;
  1553. X    if (parent == (Object *)0) {
  1554. X        newnode->next = (ObjList *)World->data;
  1555. X        World->data = (char *)newnode;
  1556. X    } else {
  1557. X        newnode->next = (ObjList *)parent->data;
  1558. X        parent->data = (char *)newnode;
  1559. X    }
  1560. X    return newobj;
  1561. X}
  1562. X
  1563. X/*
  1564. X * Return pointer to named object, NULL if no such object has been defined.
  1565. X */
  1566. XObject *
  1567. Xget_object_named(name)
  1568. Xchar *name;
  1569. X{
  1570. X    ObjList *ltmp;
  1571. X    for (ltmp = Objects; ltmp; ltmp = ltmp->next)
  1572. X        if (strcmp(name, ltmp->data->name) == 0)
  1573. X            return ltmp->data;
  1574. X    return (Object *)0;
  1575. X}
  1576. X
  1577. X/*
  1578. X * Add object to list of defined objects.
  1579. X */
  1580. Xadd_to_objects(obj)
  1581. XObject *obj;
  1582. X{
  1583. X    ObjList *ltmp;
  1584. X    extern int Verbose;
  1585. X    extern FILE *fstats;
  1586. X
  1587. X    ltmp = (ObjList *)Malloc(sizeof(ObjList));
  1588. X    ltmp->data = obj;
  1589. X    ltmp->next = Objects;
  1590. X    Objects = ltmp;
  1591. X    if (Verbose) {
  1592. X        /*
  1593. X         * Report bounding box of named object.
  1594. X         */
  1595. X        fprintf(fstats,"Object \"%s\" extent:\n", obj->name);
  1596. X        print_bounds(obj->bounds);
  1597. X    }
  1598. X}
  1599. X
  1600. X/*
  1601. X * Allocate space for a string, copy string into space.
  1602. X */
  1603. Xchar *
  1604. Xstrsave(s)
  1605. Xchar *s;
  1606. X{
  1607. X    char *tmp;
  1608. X
  1609. X    if (s == (char *)0)
  1610. X        return (char *)0;
  1611. X
  1612. X    tmp = (char *)Malloc((unsigned)strlen(s) + 1);
  1613. X    strcpy(tmp, s);
  1614. X    return tmp;
  1615. X}
  1616. X
  1617. X/*
  1618. X * Set "bounds" of primitive to be the extent of the primitive.
  1619. X */
  1620. Xset_prim_bounds(obj)
  1621. XObject *obj;
  1622. X{
  1623. X    extern int (*objextent[])();
  1624. X
  1625. X    (*objextent[((Primitive *)obj->data)->type])
  1626. X        ((Primitive *)obj->data, obj->bounds);
  1627. X    obj->bounds[LOW][X] -= EPSILON;
  1628. X    obj->bounds[HIGH][X] += EPSILON;
  1629. X    obj->bounds[LOW][Y] -= EPSILON;
  1630. X    obj->bounds[HIGH][Y] += EPSILON;
  1631. X    obj->bounds[LOW][Z] -= EPSILON;
  1632. X    obj->bounds[HIGH][Z] += EPSILON;
  1633. X}
  1634. X
  1635. END_OF_FILE
  1636. if test 4915 -ne `wc -c <'src/object.c'`; then
  1637.     echo shar: \"'src/object.c'\" unpacked with wrong size!
  1638. fi
  1639. # end of 'src/object.c'
  1640. fi
  1641. if test -f 'src/ray_options.c' -a "${1}" != "-c" ; then 
  1642.   echo shar: Will not clobber existing file \"'src/ray_options.c'\"
  1643. else
  1644. echo shar: Extracting \"'src/ray_options.c'\" \(6048 characters\)
  1645. sed "s/^X//" >'src/ray_options.c' <<'END_OF_FILE'
  1646. X/*
  1647. X * ray_options.c
  1648. X *
  1649. X * Copyright (C) 1989, Craig E. Kolb
  1650. X *
  1651. X * This software may be freely copied, modified, and redistributed,
  1652. X * provided that this copyright notice is preserved on all copies.
  1653. X *
  1654. X * There is no warranty or other guarantee of fitness for this software,
  1655. X * it is provided solely .  Bug reports or fixes may be sent
  1656. X * to the author, who may or may not act on them as he desires.
  1657. X *
  1658. X * You may not include this software in a program or other software product
  1659. X * without supplying the source, or without informing the end-user that the
  1660. X * source is available for no extra charge.
  1661. X *
  1662. X * If you modify this software, you should include a notice giving the
  1663. X * name of the person performing the modification, the date of modification,
  1664. X * and the reason for such modification.
  1665. X *
  1666. X * $Id: ray_options.c,v 3.0 89/10/27 02:06:00 craig Exp $
  1667. X *
  1668. X * $Log:    ray_options.c,v $
  1669. X * Revision 3.0  89/10/27  02:06:00  craig
  1670. X * Baseline for first official release.
  1671. X * 
  1672. X */
  1673. X#include <stdio.h>
  1674. X#ifdef SYSV
  1675. X#include <string.h>
  1676. X#else
  1677. X#include <strings.h>
  1678. X#endif
  1679. X#include "constants.h"
  1680. X#include "typedefs.h"
  1681. X
  1682. Xint Verbose;            /* Blabbering flag */
  1683. Xint TrashBadPoly;        /* Discard even mildly bad polygons */
  1684. Xint Quiet;            /* Don't be so verbose flag */
  1685. Xchar *progname;            /* argv[0] */
  1686. X
  1687. X#ifdef LINDA
  1688. Xint Workers;            /* # of workers */
  1689. X#endif
  1690. X
  1691. Xparse_options(argc, argv)
  1692. Xint argc;
  1693. Xchar **argv;
  1694. X{
  1695. X    extern char *infilename;
  1696. X    extern double RedContrast, GreenContrast, BlueContrast, atof();
  1697. X    extern int pixel_div, JitSamples, Xres, Yres, Jittered, Cache;
  1698. X    extern int Stereo, StartLine, Appending, NoShadows, ClearShadows;
  1699. X    extern double Separation, TreeCutoff;
  1700. X    extern char outfilename[];
  1701. X    extern FILE *fstats;
  1702. X
  1703. X    progname = argv[0];
  1704. X    fstats = stderr;
  1705. X
  1706. X    while(--argc) {
  1707. X        argv++;
  1708. X        if(argv[0][0] != '-')
  1709. X            break;
  1710. X        switch(argv[0][1]) {
  1711. X            case 'C':
  1712. X                RedContrast = atof(argv[1]);
  1713. X                GreenContrast = atof(argv[2]);
  1714. X                BlueContrast = atof(argv[3]);
  1715. X                argv += 3;
  1716. X                argc -= 3;
  1717. X                break;
  1718. X            case 'c':
  1719. X                ClearShadows = TRUE;
  1720. X                break;
  1721. X            case 'E':
  1722. X                Separation = atof(argv[1]);
  1723. X                argc--; argv++;
  1724. X                break;
  1725. X            case 'h':
  1726. X                usage();
  1727. X                exit(0);
  1728. X                break;
  1729. X            case 'j':
  1730. X                Jittered = TRUE;
  1731. X                break;
  1732. X            case 'L':
  1733. X                StartLine = atoi(argv[1]);
  1734. X                Appending = TRUE;
  1735. X                argc--; argv++;
  1736. X                break;
  1737. X            case 'l':
  1738. X                Stereo = LEFT;
  1739. X                break;
  1740. X            case 'n':
  1741. X                NoShadows = TRUE;
  1742. X                break;
  1743. X            case 'O':
  1744. X                strcpy(outfilename, argv[1]);
  1745. X                argv++;
  1746. X                argc--;
  1747. X                break;
  1748. X            case 'P':
  1749. X                pixel_div = atoi(argv[1]);
  1750. X                if(pixel_div < 0)
  1751. X                    pixel_div = 0;
  1752. X                argv++;
  1753. X                argc--;
  1754. X                break;
  1755. X            case 'p':
  1756. X                TrashBadPoly = TRUE;
  1757. X                break;
  1758. X            case 'q':
  1759. X                Quiet = TRUE;
  1760. X                break;
  1761. X            case 'R':
  1762. X                Xres = atoi(argv[1]);
  1763. X                Yres = atoi(argv[2]);
  1764. X                argv += 2;
  1765. X                argc -= 2;
  1766. X                break;
  1767. X            case 'r':
  1768. X                Stereo = RIGHT;
  1769. X                break;
  1770. X            case 'S':
  1771. X                JitSamples = atoi(argv[1]);
  1772. X                if (JitSamples < 1)
  1773. X                    JitSamples = 1;
  1774. X                argv++; argc--;
  1775. X                break;
  1776. X            case 's':
  1777. X                Cache = !Cache;
  1778. X                break;
  1779. X            case 'T':
  1780. X                TreeCutoff = atof(argv[1]);
  1781. X                argv++; argc--;
  1782. X                break;
  1783. X            case 'v':
  1784. X                Verbose = TRUE;
  1785. X                break;
  1786. X            case 'V':
  1787. X                Verbose = TRUE;
  1788. X                if (argv[1][0] == '-') {
  1789. X                    /* User probably blew it, and
  1790. X                     * it's difficult to remove a file
  1791. X                     * that begins with '-'...
  1792. X                     */
  1793. X                    usage();
  1794. X                    exit(2);
  1795. X                }
  1796. X                fstats = fopen(argv[1], "w");
  1797. X                if (fstats == (FILE *)0) {
  1798. X                    fprintf(stderr,"Cannot write to stats file %s\n",argv[0]);
  1799. X                    exit(2);
  1800. X                }
  1801. X                argv++; argc--;
  1802. X                break;
  1803. X#ifdef LINDA
  1804. X            case 'W':
  1805. X                Workers = atoi(argv[1]);
  1806. X                if (Workers < 0 || Workers > 17) {
  1807. X                    fprintf(stderr,"%d workers?!?\n",
  1808. X                            Workers);
  1809. X                    exit(3);
  1810. X                }
  1811. X                argv++; argc--;
  1812. X                break;
  1813. X#endif
  1814. X            default:
  1815. X                fprintf(stderr,"Bad argument: \"%s\"\n",argv[0]);
  1816. X                usage();
  1817. X                exit(1);
  1818. X        }
  1819. X    }
  1820. X
  1821. X    if(argc > 1) {
  1822. X        usage();
  1823. X        exit(1);
  1824. X    } else if(argc == 1)
  1825. X        infilename = argv[0];
  1826. X    else
  1827. X        infilename = (char *)NULL;
  1828. X
  1829. X    /*
  1830. X     * Although the user may have defined the output file name
  1831. X     * in the input file, it's best to force them to give a filename
  1832. X     * on the command line if using the -L option.  This saves situations
  1833. X     * where they forget to specify an output file to append to but
  1834. X     * aren't informed of it until startpic() is called (after the
  1835. X     * entire input file is read).
  1836. X     */
  1837. X    if (Appending && *outfilename == (char)NULL) {
  1838. X        fprintf(stderr,"The -L option requires the -O option.\n");
  1839. X        exit(4);
  1840. X    }
  1841. X
  1842. X    if (Stereo && Separation == 0.) {
  1843. X        fprintf(stderr,"You must specify eye separation (-E) in order ");
  1844. X        fprintf(stderr,"to enable Stereo mode.\n");
  1845. X        exit(4);
  1846. X    }
  1847. X}
  1848. X
  1849. Xusage()
  1850. X{
  1851. X    fprintf(stderr,"usage: %s [options] [filename]\n", progname);
  1852. X    fprintf(stderr,"Where options include:\n");
  1853. X    fprintf(stderr,"\t-C r g b\t(Set contrast threshold (0. - 1.).)\n");
  1854. X    fprintf(stderr,"\t-c \t\t(Trace shadow rays through clear objects.)\n");
  1855. X    fprintf(stderr,"\t-E eye_sep\t(Set eye separation.)\n");
  1856. X    fprintf(stderr,"\t-h \t\t(Print this message.)\n");
  1857. X    fprintf(stderr,"\t-j \t\t(Antialias using jittered sampling.)\n");
  1858. X    fprintf(stderr,"\t-L line#\t(Begin rendering at specified line.)\n");
  1859. X    fprintf(stderr,"\t-l \t\t(Render image for left eye view.)\n");
  1860. X    fprintf(stderr,"\t-n \t\t(Don't compute shadows.)\n");
  1861. X    fprintf(stderr,"\t-O outfile \t(Specify output file name.)\n");
  1862. X    fprintf(stderr,"\t-P pixel_divs\t(Set max depth for adaptive supersampling.)\n");
  1863. X    fprintf(stderr,"\t-p \t\t(Discard polygons with degenerate edges.)\n");
  1864. X    fprintf(stderr,"\t-q \t\t(Run quietly.)\n");
  1865. X    fprintf(stderr,"\t-R xres yres\t(Render at given resolution.)\n");
  1866. X    fprintf(stderr,"\t-r \t\t(Render image for right eye view.)\n");
  1867. X    fprintf(stderr,"\t-S samples\t(Use samples^2 jittered samples.)\n");
  1868. X    fprintf(stderr,"\t-s \t\t(Don't cache shadowing information.)\n");
  1869. X    fprintf(stderr,"\t-T thresh\t(Set adaptive ray tree cutoff value.)\n");
  1870. X    fprintf(stderr,"\t-V filename \t(Write verbose output to filename.)\n");
  1871. X    fprintf(stderr,"\t-v \t\t(Verbose output.)\n");
  1872. X#ifdef LINDA
  1873. X    fprintf(stderr,"\t-W workers (Specify number of worker processes.)\n");
  1874. X#endif
  1875. X}
  1876. END_OF_FILE
  1877. if test 6048 -ne `wc -c <'src/ray_options.c'`; then
  1878.     echo shar: \"'src/ray_options.c'\" unpacked with wrong size!
  1879. fi
  1880. # end of 'src/ray_options.c'
  1881. fi
  1882. if test -f 'src/voxels.c' -a "${1}" != "-c" ; then 
  1883.   echo shar: Will not clobber existing file \"'src/voxels.c'\"
  1884. else
  1885. echo shar: Extracting \"'src/voxels.c'\" \(4916 characters\)
  1886. sed "s/^X//" >'src/voxels.c' <<'END_OF_FILE'
  1887. X/*
  1888. X * voxels.c
  1889. X *
  1890. X * Copyright (C) 1989, Craig E. Kolb
  1891. X *
  1892. X * This software may be freely copied, modified, and redistributed,
  1893. X * provided that this copyright notice is preserved on all copies.
  1894. X *
  1895. X * There is no warranty or other guarantee of fitness for this software,
  1896. X * it is provided solely .  Bug reports or fixes may be sent
  1897. X * to the author, who may or may not act on them as he desires.
  1898. X *
  1899. X * You may not include this software in a program or other software product
  1900. X * without supplying the source, or without informing the end-user that the
  1901. X * source is available for no extra charge.
  1902. X *
  1903. X * If you modify this software, you should include a notice giving the
  1904. X * name of the person performing the modification, the date of modification,
  1905. X * and the reason for such modification.
  1906. X *
  1907. X * $Id: voxels.c,v 3.0 89/10/27 02:06:09 craig Exp $
  1908. X *
  1909. X * $Log:    voxels.c,v $
  1910. X * Revision 3.0  89/10/27  02:06:09  craig
  1911. X * Baseline for first official release.
  1912. X * 
  1913. X */
  1914. X#include <math.h>
  1915. X#include <stdio.h>
  1916. X#include "constants.h"
  1917. X#include "typedefs.h"
  1918. X#include "funcdefs.h"
  1919. X
  1920. X/*
  1921. X * Process World object, converting to a Grid or List.
  1922. X */
  1923. XSetupWorld()
  1924. X{
  1925. X    extern FILE *fstats;
  1926. X    extern Object *World;
  1927. X    extern int WorldXSize, WorldYSize, WorldZSize, Verbose;
  1928. X
  1929. X    if (World->type == GRID)
  1930. X        list2grid(World, WorldXSize, WorldYSize, WorldZSize);
  1931. X    else
  1932. X        make_list(World);
  1933. X
  1934. X    if (Verbose) {
  1935. X        fprintf(fstats,"World extent:\n");
  1936. X        print_bounds(World->bounds);
  1937. X    }
  1938. X}
  1939. X
  1940. X/*
  1941. X * Add object to grid's unbounded list.
  1942. X */
  1943. Xmake_unbounded(obj, grid)
  1944. XObject *obj;
  1945. XGrid *grid;
  1946. X{
  1947. X    ObjList *tmp;
  1948. X
  1949. X    tmp = (ObjList *)Malloc(sizeof(ObjList));
  1950. X
  1951. X    tmp->data = obj;
  1952. X    tmp->next = grid->unbounded;
  1953. X    grid->unbounded = tmp;
  1954. X}
  1955. X
  1956. X/*
  1957. X * Place an object in a grid.
  1958. X */
  1959. Xengrid(obj, grid)
  1960. XObject *obj;
  1961. XGrid *grid;
  1962. X{
  1963. X    int x, y, z, low[3], high[3];
  1964. X    ObjList *ltmp;
  1965. X
  1966. X    /*
  1967. X     * This routine should *never* be passed an unbounded object, but...
  1968. X     */
  1969. X    if (pos2grid(grid, obj->bounds[LOW], low) == 0 ||
  1970. X        pos2grid(grid, obj->bounds[HIGH], high) == 0 ||
  1971. X        obj->bounds[LOW][X] > obj->bounds[HIGH][X]) {
  1972. X        /*
  1973. X         * Object is partially on wholly outside of
  1974. X         * grid -- this should never happen, but just
  1975. X         * in case...
  1976. X         */
  1977. X        make_unbounded(obj, grid);
  1978. X        fprintf(stderr,"Strange, engrid got an unbounded object...\n");
  1979. X        return;
  1980. X        }
  1981. X
  1982. X    /*
  1983. X     * For each voxel that intersects the object's bounding
  1984. X     * box, add pointer to this object to voxel's linked list.
  1985. X      */
  1986. X    for (x = low[X]; x <= high[X]; x++) {
  1987. X        for (y = low[Y]; y <= high[Y]; y++) {
  1988. X            for (z = low[Z]; z <= high[Z]; z++) {
  1989. X                ltmp = (ObjList *)share_malloc(sizeof(ObjList));
  1990. X                ltmp->data = obj;
  1991. X                ltmp->next = grid->cells[x][y][z];
  1992. X                grid->cells[x][y][z] = ltmp;
  1993. X            }
  1994. X        }
  1995. X    }
  1996. X}
  1997. X
  1998. X/*
  1999. X * Convert 3D point to index into grid's voxels.
  2000. X */
  2001. Xpos2grid(grid, pos, index)
  2002. XGrid *grid;
  2003. Xdouble pos[3];
  2004. Xint index[3];
  2005. X{
  2006. X    index[X] = (int)(x2voxel(grid, pos[0]));
  2007. X    index[Y] = (int)(y2voxel(grid, pos[1]));
  2008. X    index[Z] = (int)(z2voxel(grid, pos[2]));
  2009. X
  2010. X    if (index[X] == grid->xsize)
  2011. X        index[X] = grid->xsize -1;
  2012. X    if (index[Y] == grid->ysize)
  2013. X        index[Y] = grid->ysize -1;
  2014. X    if (index[Z] == grid->zsize)
  2015. X        index[Z] = grid->zsize -1;
  2016. X
  2017. X    if (index[X] < 0 || index[X] >= grid->xsize ||
  2018. X        index[Y] < 0 || index[Y] >= grid->ysize ||
  2019. X        index[Z] < 0 || index[Z] >= grid->zsize)
  2020. X        return 0;
  2021. X    return 1;
  2022. X}
  2023. X
  2024. X/*
  2025. X * Convert a linked list of objects to a Grid.
  2026. X */
  2027. Xlist2grid(obj, xsize, ysize, zsize)
  2028. XObject *obj;
  2029. Xint xsize, ysize, zsize;
  2030. X{
  2031. X    Grid *grid;
  2032. X    Object *otmp;
  2033. X    ObjList *ltmp;
  2034. X    int x, y, i;
  2035. X    extern ObjList *find_bounds();
  2036. X
  2037. X    grid = (Grid *)Malloc(sizeof(Grid));
  2038. X
  2039. X    /*
  2040. X     * Find bounding box of bounded objects and get list of
  2041. X     * unbounded objects.
  2042. X     */
  2043. X    grid->unbounded = find_bounds((ObjList **)&obj->data, obj->bounds);
  2044. X
  2045. X    grid->xsize = xsize; grid->ysize = ysize; grid->zsize = zsize;
  2046. X
  2047. X    for (i = 0; i < 3; i++) {
  2048. X        obj->bounds[LOW][i] -= 2. * EPSILON;
  2049. X        obj->bounds[HIGH][i] += 2. * EPSILON;
  2050. X        grid->bounds[LOW][i] = obj->bounds[LOW][i];
  2051. X        grid->bounds[HIGH][i] = obj->bounds[HIGH][i];
  2052. X    }
  2053. X    grid->voxsize[X] = (grid->bounds[HIGH][X]-grid->bounds[LOW][X])/xsize;
  2054. X    grid->voxsize[Y] = (grid->bounds[HIGH][Y]-grid->bounds[LOW][Y])/ysize;
  2055. X    grid->voxsize[Z] = (grid->bounds[HIGH][Z]-grid->bounds[LOW][Z])/zsize;
  2056. X
  2057. X    /*
  2058. X     * Allocate voxels.
  2059. X     */
  2060. X    grid->cells = (ObjList ****)share_malloc(xsize * sizeof(ObjList ***));
  2061. X    for (x = 0; x < xsize; x++) {
  2062. X        grid->cells[x] = (ObjList ***)share_malloc(ysize*sizeof(ObjList **));
  2063. X        for (y = 0; y < ysize; y++)
  2064. X            grid->cells[x][y] = (ObjList **)share_calloc((unsigned)zsize,
  2065. X                            sizeof(ObjList *));
  2066. X    }
  2067. X
  2068. X    /*
  2069. X     * obj->data now holds a linked list of bounded objects.
  2070. X     */
  2071. X    for(ltmp = (ObjList *)obj->data; ltmp; ltmp = ltmp->next) {
  2072. X        otmp = ltmp->data;
  2073. X        engrid(otmp, grid);
  2074. X        free(ltmp);
  2075. X    }
  2076. X    obj->type = GRID;
  2077. X    obj->data = (char *)grid;
  2078. X}
  2079. X#ifdef MULTIMAX
  2080. X
  2081. Xchar *
  2082. Xshare_calloc(num, siz)
  2083. Xint num;
  2084. Xunsigned int siz;
  2085. X{
  2086. X    char *res;
  2087. X
  2088. X    res = share_malloc(num*siz);
  2089. X    bzero(res, num*siz);
  2090. X    return res;
  2091. X}
  2092. X#endif
  2093. END_OF_FILE
  2094. if test 4916 -ne `wc -c <'src/voxels.c'`; then
  2095.     echo shar: \"'src/voxels.c'\" unpacked with wrong size!
  2096. fi
  2097. # end of 'src/voxels.c'
  2098. fi
  2099. echo shar: End of archive 3 \(of 8\).
  2100. cp /dev/null ark3isdone
  2101. MISSING=""
  2102. for I in 1 2 3 4 5 6 7 8 ; do
  2103.     if test ! -f ark${I}isdone ; then
  2104.     MISSING="${MISSING} ${I}"
  2105.     fi
  2106. done
  2107. if test "${MISSING}" = "" ; then
  2108.     echo You have unpacked all 8 archives.
  2109.     rm -f ark[1-9]isdone
  2110. else
  2111.     echo You still need to unpack the following archives:
  2112.     echo "        " ${MISSING}
  2113. fi
  2114. ##  End of shell archive.
  2115. exit 0
  2116.  
  2117.  
  2118.